package com.vgemv.jsutilitysdk.activity.ChooseApp;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.RecyclerView;

import com.vgemv.jsutilitysdk.Display.JsActivityContentDisplayManager.JsActivityContentDisplayManager;
import com.vgemv.jsutilitysdk.JsThread.JsThreadManager;
import com.vgemv.jsutilitysdk.Menu.JsMenuView.JsMenuItemView.JsMenuItemView;
import com.vgemv.jsutilitysdk.Menu.JsMenuView.JsMenuItemVm.JsMenuItemVm;
import com.vgemv.jsutilitysdk.Menu.JsMenuView.JsMenuView;
import com.vgemv.jsutilitysdk.Menu.JsMenuView.JsMenuViewAdapter;
import com.vgemv.jsutilitysdk.Menu.JsMenuView.JsMenuViewBasicCallback;
import com.vgemv.jsutilitysdk.Menu.JsMenuView.JsMenuViewVm;
import com.vgemv.jsutilitysdk.R;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;


public class JsChooseAppActivity extends AppCompatActivity {
    //全部应用的数据
    private ArrayList<JsMenuItemVm> al_appVm;
    //过滤之后的数据
    private ArrayList<JsMenuItemVm> al_appVm_filter;
    private ArrayList<JsMenuItemVm> al_appVm_cache;

    private JsMenuView mMenuView;
    private RelativeLayout mrl_root;
    private String TAG = JsChooseAppActivity.class.getSimpleName();

    public static String APP_PACKAGE_NAME = "APP_PACKAGE_NAME";
    public static int resultCode = 1;

    private Drawable drawable_defualtIcon = null;
    //getDrawable(R.mipmap.ic_launcher);

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActionBar actionBar = getSupportActionBar();
        if(actionBar != null) {
            //设置返回按钮的图标.
//            actionBar.setHomeAsUpIndicator();
            actionBar.setDisplayHomeAsUpEnabled(true);
        }
//        this.requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
//        this.getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.);
        mrl_root = new RelativeLayout(this);
        drawable_defualtIcon = getResources().getDrawable(R.mipmap.ic_launcher);
        setContentView(mrl_root);
        al_appVm = new ArrayList();
        al_appVm_filter = new ArrayList<>();
        al_appVm_cache = new ArrayList<>();
        mMenuView = new JsMenuView(this);
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        mrl_root.addView(mMenuView,lp);
        //耗时异步任务放到子线程,先加载.
        JsActivityContentDisplayManager.sharedInstance().displayLoadingReminder(this);
        JsThreadManager.dispatchAsyncMainCallback(new Runnable() {
            @Override
            public void run() {
                scanInstalledApp();
                al_appVm_cache.addAll(al_appVm);
            }
        }, new Runnable() {
            @Override
            public void run() {
                JsActivityContentDisplayManager.sharedInstance().undisplayLoadingReminder(JsChooseAppActivity.this);
                customReloadData(false);
            }
        });

        mMenuView.mBasicCallback = new JsMenuViewBasicCallback() {
            @Override
            public ArrayList<JsMenuItemVm> jsMenuViewSetDatasource() {
                return al_appVm_filter;
            }

            @Override
            public void jsMenuViewClickItem(JsMenuView menuView, int i, JsMenuItemVm vm) {
                JsAppItemVm jsAppItemVm = (JsAppItemVm) vm;
                Intent intent = getIntent();
                JsAppItemModel model = (JsAppItemModel)vm.currentModel();
                intent.putExtra(APP_PACKAGE_NAME,model.packageName);
                model.printfInfo();
                setResult(resultCode,intent);
                finish();
            }

            @Override
            public JsMenuItemView jsMenuViewCreateItemView(JsMenuView menuView, Context context) {
                JsAppItemView appItemView = new JsAppItemView(context);
                return appItemView;
            }

            @Override
            public void jsMenuViewAfterCreateView(JsMenuView menuView) {

            }

            @Override
            public JsMenuViewVm jsMenuViewSetVm(JsMenuView menuView) {
                JsMenuViewVm vm = new JsMenuViewVm();
                vm.mi_layoutStyle = 2;
                return vm;
            }

            @Override
            public Rect jsMenuViewSetItemOffset(JsMenuView menuView, int index) {
                Rect rect = new Rect();
                int space = 10;
                rect.left = space;
                rect.right = space;
                rect.bottom = space;
                if (index == 0) {
                    rect.top = space;
                }
                return rect;
            }

            @Override
            public JsMenuViewAdapter jsMenuViewSetAdapter(JsMenuView menuView) {
                return null;
            }

            @Override
            public void jsMenuItemViewWillDisplay(RecyclerView.ViewHolder viewHolder, int position) {
                JsAppItemView appItemView = (JsAppItemView)viewHolder.itemView;
                JsAppItemVm vm = (JsAppItemVm) al_appVm_filter.get(position);
                appItemView.setVm(vm);
            }
        };

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.js_choose_app_activity_menu, menu);
            // "版本的控制"，如果低于3.0版本的就不执行此方法
            if(android.os.Build.VERSION.SDK_INT > 11){
                MenuItem menuItem = menu.findItem(R.id.action_search);
                SearchView searchView = (SearchView) menuItem.getActionView();
                searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        al_appVm_cache = getFilterData(al_appVm,query);
                        customReloadData(true);
//                        return false;
                        return true;
                    }

                    @Override
                    public boolean onQueryTextChange(String newText) {
                        al_appVm_cache = getFilterData(al_appVm,newText);
                        customReloadData(true);
//                        return false;
                        return true;
                    }
                });
            }
            return true;
    }

    private void customReloadData(boolean isAnimation) {
        if(!isAnimation) {
            al_appVm_filter.clear();
            al_appVm_filter.addAll(al_appVm_cache);
            mMenuView.reloadData();
        }
        else {
            int latestSize = al_appVm_filter.size();
            int currentSize = al_appVm_cache.size();

            if (currentSize == 0 || latestSize == 0) {
                al_appVm_filter.clear();
                al_appVm_filter.addAll(al_appVm_cache);
                mMenuView.reloadData();
            } else if (currentSize < latestSize) {
                //搜索结果减小.
                //如果是只有一个元素,在中间就是2个区间,在边边,就是1个区间.
                //如果2个元素,都在中间是3个,1个在边边是1个,2个都在边边,是1个.
                //如果3个元素,都在中间是4个,1个边边
                int rangeStartPosition = -1;
                int rangeEndPosition = -1;
                int totalCount = 0;
                int count = 0;
                for (int i = 0; i < al_appVm_cache.size(); i++) {
                    JsAppItemVm vm = (JsAppItemVm) al_appVm_cache.get(i);
                    int latestPosition = al_appVm_filter.indexOf(vm);
                    int currentPosition = i;
                    if (latestPosition == currentPosition) {
                        //无需操作.
                    } else {
                        //当前元素位置有变动.
                        if (rangeStartPosition == -1) {
                            rangeStartPosition = 0;
                        }
                        rangeEndPosition = latestPosition - 1;
                        count = rangeEndPosition - rangeStartPosition + 1;
                        if (count > 0) {
                            totalCount += count;
                            String info = String.format("delete range:[%d,%d]", rangeStartPosition, rangeEndPosition);
                            Log.d(TAG, info);
                            al_appVm_filter.subList(rangeStartPosition,rangeEndPosition+1).clear();
                            mMenuView.reloadDataRangeRemoved(rangeStartPosition, count);
                        }
                    }
                    //下一轮
                    rangeStartPosition = latestPosition + 1 - count;
                }
                //最后的区域.
                if (al_appVm_filter.size() > currentSize) {
                    rangeEndPosition = al_appVm_filter.size() - 1;
                    count = rangeEndPosition - rangeStartPosition + 1;
                    totalCount += count;
                    String info = String.format("delete range:[%d,%d]", rangeStartPosition, rangeEndPosition);
                    Log.d(TAG, info);
                    al_appVm_filter.subList(rangeStartPosition,rangeEndPosition+1).clear();
                    mMenuView.reloadDataRangeRemoved(rangeStartPosition, count);
                }
                String info = String.format("total delete %d item.", totalCount);
                Log.d(TAG, info);
            } else if (currentSize > latestSize) {
                //当前数组中增加的区域.
                int rangeStartPosition = -1;
                int rangeEndPosition = -1;
                int currentPosition = -1;
                int latestPosition = -1;
                int count = 0;
                //遍历少的那个数组.
                for (int i = 0; i < al_appVm_filter.size(); i++) {
                    JsAppItemVm vm = (JsAppItemVm) al_appVm_filter.get(i);
                     currentPosition = al_appVm_cache.indexOf(vm);
                    latestPosition = i;
                    if (latestPosition == currentPosition) {
                        //无需操作.
                    } else {
                        if (rangeStartPosition == -1) {
                            rangeStartPosition = 0;

                        }
                        rangeEndPosition = currentPosition - 1;
                        count = rangeEndPosition - rangeStartPosition + 1;
                        if (count > 0) {
                            String info = String.format("inserted range:[%d,%d]", rangeStartPosition, rangeEndPosition);
                            Log.d(TAG, info);
                            al_appVm_filter.addAll(rangeStartPosition,al_appVm_cache.subList(rangeStartPosition,rangeEndPosition+1));
                            mMenuView.reloadDataRangeInserted(rangeStartPosition, count);
                        }
                    }
                    rangeStartPosition = currentPosition + 1;
                }
                //增加到末尾
                if (al_appVm_filter.size() < currentSize) {
                    rangeEndPosition = currentSize - 1;
                    String info = String.format("inserted range:[%d,%d]", rangeStartPosition, rangeEndPosition);
                    Log.d(TAG, info);
                    //插入到末尾.
                    al_appVm_filter.addAll(al_appVm_cache.subList(rangeStartPosition,rangeEndPosition+1));
                    mMenuView.reloadDataRangeInserted(rangeStartPosition, rangeEndPosition - rangeStartPosition + 1);
                }
                mMenuView.scrollToTop();
            }
        }
    }

    //Activity创建时,其Context并未创建
    private void scanInstalledApp() {
        List<ResolveInfo> al_result = new ArrayList<>();
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        //Q:这个标志有什么用?
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED );
        PackageManager packageManager = getPackageManager();
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            al_result = packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL);
        }
        else {
            al_result = packageManager.queryIntentActivities(intent,0);
        }
        String info = String.format("There are %d app.",al_result.size());
        Log.v(TAG,info);
        for (ResolveInfo resolveInfo : al_result) {
            JsAppItemVm jsAppItemVm = new JsAppItemVm();
            //info.activityInfo.applicationInfo.packageName
            //info.activityInfo.applicationInfo.name
            String packageName = resolveInfo.activityInfo.applicationInfo.packageName;
            Log.v(TAG,packageName);
            JsAppItemModel model = new JsAppItemModel();
            model.appName = getAppName(resolveInfo.activityInfo.applicationInfo);
            model.packageName = packageName;
            model.drawable_icon = getAppIcon(resolveInfo.activityInfo.applicationInfo);
            model.resolveInfo = resolveInfo;
            jsAppItemVm.setModel(model);
            al_appVm.add(jsAppItemVm);
        }

    }


    private ArrayList<JsMenuItemVm> getFilterData(ArrayList al_origin, String key) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return getFilterData_24(al_origin,key);
        }
        else {
            //TODO: API level < 21 适配数组过滤功能.
            return al_origin;
        }
    }

     @RequiresApi(api = Build.VERSION_CODES.N)
     private ArrayList<JsMenuItemVm> getFilterData_24(ArrayList al_origin, String key) {
        ArrayList<JsMenuItemVm> al = (ArrayList<JsMenuItemVm>) al_origin.stream().filter(new Predicate<JsMenuItemVm>() {
            @Override
            public boolean test(JsMenuItemVm jsMenuItemVm) {
                if(key == null || key.length() == 0) {
                    return true;
                }
                else {
                    JsAppItemModel vm = (JsAppItemModel) jsMenuItemVm.currentModel();
                    return vm.appName.contains(key);
                }
            }
        }).collect(Collectors.toList());
        return al;
     }

    public String getAppName(String ApkPackageName){
        String appName = "";
        ApplicationInfo applicationInfo;
        PackageManager packageManager = getPackageManager();
        try {
            applicationInfo = packageManager.getApplicationInfo(ApkPackageName, 0);
            if(applicationInfo!=null){
                appName = (String)packageManager.getApplicationLabel(applicationInfo);
            }
        }catch (PackageManager.NameNotFoundException e) {

            e.printStackTrace();
        }
        return appName;
    }
    public String getAppName(ApplicationInfo applicationInfo) {
        String appName = "";
        PackageManager packageManager = getPackageManager();
        try {
            appName = (String) packageManager.getApplicationLabel(applicationInfo);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return  appName;
    }

    //这个方法在很多icon时会耗时.
    public Drawable getAppIcon(String packageName){
        Drawable drawable = null;
        try{
            drawable = getPackageManager().getApplicationIcon(packageName);
        }
        catch (PackageManager.NameNotFoundException e){
            e.printStackTrace();
            drawable = drawable_defualtIcon;
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        return drawable;
    }

    public Drawable getAppIcon(ApplicationInfo applicationInfo) {
        Drawable drawable = null;
        try{
            drawable = getPackageManager().getApplicationIcon(applicationInfo);
        }
        catch (Exception e) {
            drawable = drawable_defualtIcon;
            e.printStackTrace();
        }
        return drawable;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home: {
                finish();
                break;
            }
            default: {

            }
        }
        return super.onOptionsItemSelected(item);
    }
}
